﻿#ifndef SERIALPORT_H
#define SERIALPORT_H
#include <deque>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTimer>

class MainWindow;
class SerialPort : public QObject {
	Q_OBJECT
public:
	// 待确诊消息
	struct waitConfirmMsg {
		std::time_t timePoint;     // 发送消息的时间点
		QByteArray sendMsg;
	};
	// 中继转发
	static const uint32_t relayCmd = 0xe3020001;
	// 查终端编号
	static const uint32_t queryTerminalNoReq = 0xe8000303;
	static const uint32_t queryTerminalNoRsp = 0xe8000303;
	// 启动台区识别
	static const uint32_t startAreaIdentifyReq = 0xe8020480;
	static const uint32_t startAreaIdentifyRsp = 0xe8010001;
	// 查询表档案的台区识别结果
	static const uint32_t queryTableFileAreaResultReq = 0xe803030e;
	static const uint32_t queryTableFileAreaResultRsp = 0xe804030e;
	// 查询多余节点的台区识别结果
	static const uint32_t queryRedundantAreaResultReq = 0xe803030f;
	static const uint32_t queryRedundantAreaResultRsp = 0xe804030f;
	// 查询从结点数量
	static const uint32_t queryNodeNumberReq = 0xe8000305;
	static const uint32_t queryNodeNumberRsp = 0xe8000305;
	// 批量查询从节点相位信息
	static const uint32_t batchQueryNodePhaseInfoReq = 0xe803030d;
	static const uint32_t batchQueryNodePhaseInfoRsp = 0xe804030d;
	// 启动搜表
	static const uint32_t startSearchTableReq = 0xe8020405;
	static const uint32_t startSearchTableRsq = 0xe8010001;
	// 从节点信息上报
	static const uint32_t slaveNodeReport = 0xe8050503;
	// 停止搜表
	static const uint32_t stopSearchTableReq = 0xe8020406;
	static const uint32_t stopSearchTableRsq = 0xe8010001;
	// 查询从节点信息
	static const uint32_t queryNodeInfoReq = 0xe8030365;
	static const uint32_t queryNodeInfoRsp = 0xe8040365;

	SerialPort(MainWindow& mw);
	bool init(const QString& portName);
	void close();
	std::vector<QString> findFreePorts();
	void sendMsg(const QByteArray& msg);

	void startWaitConfirmTimer(uint32_t ms);
	bool cacheWaitConfirmMsg(uint32_t cmd, const QByteArray& msg);
	void confirmWaitConfirmMsg(uint32_t cmd);

	void handleMsg(const QByteArray& msg);

	// 报文头
	std::vector<int> msgHead = { 0x68, 0x27, 0x00, 0x27, 0x00, 0x68, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x60, 0x00, 0x00, 0x01, 0x00, 0x02, 0xE3, 0x00, 0x1F, 0x20, 0x01, 0x08, 0x00, 0x01, 0x0F };

public slots:
	void sendMsgCycle();
	void recvMsg();

	// 一秒检查一次未确认的消息，长时间未确认的，按需求重发
	void checkWaitConfirmMsg();

private:
	MainWindow& mainWindow;

	QSerialPort* serialPort;
	std::deque<QByteArray> waitSendMsgs;
	QTimer* sendMsgTimer;
	QByteArray recvMsgBuffer;

	std::map<uint32_t, waitConfirmMsg> waitConfirmMsgs;
	QTimer* waitConfirmTimer;
};


#endif
